local assets_arong = {
	Asset("ANIM", "anim/beefalo_basic.zip"),
	Asset("ANIM", "anim/beefalo_actions.zip"),
	Asset("ANIM", "anim/beefalo_actions_domestic.zip"),
	Asset("ANIM", "anim/beefalo_actions_quirky.zip"),
	Asset("ANIM", "anim/musha_arong.zip"),
	Asset("ANIM", "anim/musha_arong_personality_docile.zip"),
	Asset("ANIM", "anim/musha_arong_personality_ornery.zip"),
	Asset("ANIM", "anim/musha_arong_personality_pudgy.zip"),
	Asset("ANIM", "anim/beefalo_fx.zip"),
	Asset("SOUND", "sound/beefalo.fsb")
}

local assets_arom = {
	Asset("ANIM", "anim/beefalo_basic.zip"),
	Asset("ANIM", "anim/beefalo_actions.zip"),
	Asset("ANIM", "anim/beefalo_actions_domestic.zip"),
	Asset("ANIM", "anim/beefalo_actions_quirky.zip"),
	Asset("ANIM", "anim/musha_arom.zip"),
	Asset("ANIM", "anim/musha_arom_personality_docile.zip"),
	Asset("ANIM", "anim/musha_arom_personality_ornery.zip"),
	Asset("ANIM", "anim/musha_arom_personality_pudgy.zip"),
	Asset("ANIM", "anim/beefalo_fx.zip"),
	Asset("SOUND", "sound/beefalo.fsb")
}

local prefabs = {
	"poop",
	"beefalowool",
	"horn"
}

local brain = require("brains/musha_beefalobrain")

SetSharedLootTable(
	"musha_arong",
	{
		{"beefalowool", 0.50},
		{"beefalowool", 0.50},
		{"beefalowool", 0.50},
		{"beefalowool", 0.50},
		{"meat", 1.00},
		{"meat", 1.00},
		{"meat", 1.00},
		{"meat", 0.50},
		{"horn", 1.00},
		{"horn", 1.00}
	}
)
SetSharedLootTable(
	"musha_arom",
	{
		{"beefalowool", 0.50},
		{"beefalowool", 0.50},
		{"beefalowool", 0.50},
		{"beefalowool", 0.50},
		{"meat", 1.00},
		{"meat", 1.00},
		{"meat", 0.50},
		{"meat", 0.50},
		{"horn", 1.00}
	}
)

local sounds = {
	walk = "dontstarve/beefalo/walk",
	grunt = "dontstarve/beefalo/grunt",
	yell = "dontstarve/beefalo/yell",
	swish = "dontstarve/beefalo/tail_swish",
	curious = "dontstarve/beefalo/curious",
	angry = "dontstarve/beefalo/angry",
	sleep = "dontstarve/beefalo/sleep"
}

local tendencies = {
	arong = {
		DEFAULT = {},
		ORNERY = {
			build = "musha_arong_personality_ornery"
		},
		RIDER = {
			build = "musha_arong_personality_docile"
		},
		PUDGY = {
			build = "musha_arong_personality_pudgy",
			customactivatefn = function(inst)
				--inst:AddComponent("sanityaura")
				inst.components.sanityaura.aura = TUNING.SANITYAURA_SMALL_TINY
			end,
			customdeactivatevn = function(inst)
				-- inst:RemoveComponent("sanityaura")
				inst.components.sanityaura.aura = TUNING.SANITYAURA_TINY
			end
		}
	},
	arom = {
		DEFAULT = {},
		ORNERY = {
			build = "musha_arom_personality_ornery"
		},
		RIDER = {
			build = "musha_arom_personality_docile"
		},
		PUDGY = {
			build = "musha_arom_personality_pudgy",
			customactivatefn = function(inst)
				--inst:AddComponent("sanityaura")
				inst.components.sanityaura.aura = TUNING.SANITYAURA_SMALL_TINY
			end,
			customdeactivatevn = function(inst)
				-- inst:RemoveComponent("sanityaura")
				inst.components.sanityaura.aura = TUNING.SANITYAURA_TINY
			end
		}
	}
}

local function order(inst, commander, action)
	if inst.ownerid == commander.userid then
		if not inst:IsNear(commander, 20) then
			commander.components.talker:Say(STRINGS.MUSHA_TALK_ORDER_ARONG_LOST)
			return
		end
		if action == "follow" then
			inst.components.follower:SetLeader(commander)
			commander.components.talker:Say(STRINGS.MUSHA_TALK_ORDER_ARONG_FOLLOW)
		elseif action == "stay" then
			inst.components.follower:SetLeader(nil)
			commander.components.talker:Say(STRINGS.MUSHA_TALK_ORDER_ARONG_STAY)
		end
	end
end

local function ClearBuildOverrides(inst, animstate)
	if animstate ~= inst.AnimState then
		animstate:ClearOverrideBuild(inst.name .. "_build")
	end
	animstate:ClearOverrideBuild(inst.name .. "_personality_docile")
end

-- This takes an anim state so that it can apply to itself, or to its rider
local function ApplyBuildOverrides(inst, animstate)
	--  local herd = inst.components.herdmember and inst.components.herdmember:GetHerd()
	local basebuild =
		(inst:HasTag("baby") and inst.name .. "_baby_build") or
		(inst.components.domesticatable:IsDomesticated() and inst.name .. "_build") or
		inst.name .. "_build"
	if animstate ~= nil and animstate ~= inst.AnimState then
		animstate:AddOverrideBuild(basebuild)
	else
		animstate:SetBuild(basebuild)
	end

	--[[if (herd and herd.components.mood and herd.components.mood:IsInMood()) or
    (inst.components.mood and inst.components.mood:IsInMood()) then
    animstate:Show("HEAT")
    else
    animstate:Hide("HEAT")
    end]]
	if tendencies[inst.name][inst.tendency].build ~= nil then
		animstate:AddOverrideBuild(tendencies[inst.name][inst.tendency].build)
	elseif animstate == inst.AnimState then
		-- this presumes that all the face builds have the same symbols
		animstate:ClearOverrideBuild(inst.name .. "_personality_docile")
	end
end

local function OnOpen(inst, data)
	if data.doer:HasTag("monkey") then
		inst.components.talker:Say(RandomChoice(STRINGS.MUSHA_TALK_THIEF))
		inst.components.container:Close()
	end
	--inst.openc = true
	if not inst.components.health:IsDead() then
		inst.components.combat:SetTarget(nil)
		inst.components.combat:GiveUp()

		if not inst.components.sleeper:IsAsleep() then
			inst.sg:GoToState("pleased")
		elseif inst.components.sleeper:IsAsleep() then
			inst.sg:GoToState("shaved")
		end
		inst.SoundEmitter:PlaySound("dontstarve/beefalo/saddle/shake_off")
	end
	if inst.components.burnable:IsBurning() then
		inst.components.burnable:Extinguish()
	end
	if inst.components.freezable:IsFrozen() then
		inst.components.freezable:Unfreeze()
	end
end

local function OnClose(inst)
	--inst.openc = false
	if not inst.components.health:IsDead() then
		inst.SoundEmitter:PlaySound("dontstarve/beefalo/saddle/shake_off")
		if inst.AnimState:IsCurrentAnimation("alert_idle") then
			inst.AnimState:PlayAnimation("alert_pre")
		end
		if not inst.components.sleeper:IsAsleep() then
			inst.sg:GoToState("refuse")
		elseif inst.components.sleeper:IsAsleep() then
			inst.sg:GoToState("shaved")
		end
	end
end

local function OnEnterMood(inst)
	--inst:AddTag("scarytoprey")
	inst:ApplyBuildOverrides(inst.AnimState)
	if inst.components.rideable and inst.components.rideable:GetRider() ~= nil then
		inst:ApplyBuildOverrides(inst.components.rideable:GetRider().AnimState)
	end
end

local function OnLeaveMood(inst)
	--inst:RemoveTag("scarytoprey")
	inst:ApplyBuildOverrides(inst.AnimState)
	if inst.components.rideable ~= nil and inst.components.rideable:GetRider() ~= nil then
		inst:ApplyBuildOverrides(inst.components.rideable:GetRider().AnimState)
	end
end

local function Retarget(inst)
	local leader = inst.components.follower.leader
	if
		inst.components.follower and inst.components.follower.leader and leader.components.health:GetPercent() < .4 and
			inst.components.health:GetPercent() > 0.2
	 then
		return FindEntity(
			inst,
			TUNING.BEEFALO_TARGET_DIST * 1.2,
			function(guy)
				return inst.components.combat:CanTarget(guy)
			end,
			nil,
			{
				"_musha",
				"_musha_follower",
				"beefalo"
			}
		)
	end
end

local function KeepTarget(isnt, target)
	return target and target:IsValid() and not target:HasTag("player")
end

local function flower_shield(inst, data)
	if data ~= nil and data.attacker and data.attacker.components.sleeper and inst.components.health:GetPercent() <= .5 then
		data.attacker.components.sleeper:AddSleepiness(3, 24)
		SpawnPrefab("small_puff").Transform:SetPosition(data.attacker:GetPosition():Get())
	end
	if not inst.components.health:IsDead() then
		if inst.components.health:GetPercent() >= .8 then
			SpawnPrefab("green_leaves").Transform:SetPosition(inst:GetPosition():Get())
		elseif inst.components.health:GetPercent() < .8 and inst.components.health:GetPercent() >= .6 then
			SpawnPrefab("yellow_leaves").Transform:SetPosition(inst:GetPosition():Get())
		elseif inst.components.health:GetPercent() < .6 and inst.components.health:GetPercent() >= .4 then
			SpawnPrefab("orange_leaves").Transform:SetPosition(inst:GetPosition():Get())
		elseif inst.components.health:GetPercent() < .4 then
			SpawnPrefab("red_leaves").Transform:SetPosition(inst:GetPosition():Get())
		elseif inst.components.health:GetPercent() < .1 then
			inst.components.combat:SetTarget(nil)
			inst.components.combat:GiveUp()
		end
	end
end

local function CanShareTarget(dude)
	return (dude:HasTag("beefalo") or dude:HasTag("companion")) and not dude:IsInLimbo() and
		not (dude.components.health:IsDead())
end

local function OnAttacked(inst, data)
	if inst._ridersleeptask ~= nil then
		inst._ridersleeptask:Cancel()
		inst._ridersleeptask = nil
	end
	inst._ridersleep = nil

	if not inst.components.rideable:IsBeingRidden() then
		if data.attacker ~= nil and data.attacker:HasTag("player") then --#TODO: pvp
			inst.components.combat:SetTarget(nil)
			inst.components.combat:GiveUp()
		else
			inst.components.combat:SetTarget(data.attacker)
			inst.components.combat:ShareTarget(data.attacker, 30, CanShareTarget, 5)
		end
	end
end

local function GetStatus(inst)
	return (inst.components.follower.leader ~= nil and "FOLLOWER") or
		--or (inst.components.beard ~= nil and inst.components.beard.bits == 0 and "NAKED")
		(inst.components.domesticatable ~= nil and inst.components.domesticatable:IsDomesticated() and
			(inst.tendency == TENDENCY.DEFAULT and "DOMESTICATED" or inst.tendency)) or
		nil
end

local function ShouldAcceptItem(inst, item)
	return inst.components.eater:CanEat(item) and not inst.components.combat:HasTarget()
end

local function OnGetItemFromPlayer(inst, giver, item)
	if inst.components.eater:CanEat(item) then
		inst.components.eater:Eat(item)
	end
end

local function OnRefuseItem(inst, item)
	inst.sg:GoToState("refuse")
	if inst.components.sleeper:IsAsleep() then
		inst.components.sleeper:WakeUp()
	end
end

local function OnDomesticated(inst, data)
	inst.components.rideable:Buck()
	inst.domesticationPending = true
end

local function DoDomestication(inst)
	inst:SetTendency()
end

local function OnFeral(inst, data)
	inst.components.rideable:Buck()
	inst.domesticationPending = true
end

local function DoFeral(inst)
	--inst.components.herdmember:Enable(true)
	--inst.components.mood:Enable(false)
	--inst.components.mood:ValidateMood()
	inst:SetTendency()
end

local function UpdateDomestication(inst)
	if inst.components.domesticatable:IsDomesticated() then
		DoDomestication(inst)
	else
		DoFeral(inst)
	end
end

local function SetTendency(inst, changedomestication)
	-- tendency is locked in after we become domesticated
	local tendencychanged = false
	local oldtendency = inst.tendency
	if not inst.components.domesticatable:IsDomesticated() then
		local tendencysum = 0
		local maxtendency = nil
		local maxtendencyval = 0
		for k, v in pairs(inst.components.domesticatable.tendencies) do
			tendencysum = tendencysum + v
			if v > maxtendencyval then
				maxtendencyval = v
				maxtendency = k
			end
		end
		inst.tendency = (tendencysum < .1 or maxtendencyval * 2 < tendencysum) and TENDENCY.DEFAULT or maxtendency
		tendencychanged = inst.tendency ~= oldtendency
	end

	if changedomestication == "domestication" then
		if tendencies[inst.name][inst.tendency].customactivatefn ~= nil then
			tendencies[inst.name][inst.tendency].customactivatefn(inst)
		end
	elseif changedomestication == "feral" and tendencies[inst.name][oldtendency].customdeactivatefn ~= nil then
		tendencies[inst.name][oldtendency].customdeactivatefn(inst)
	end

	if tendencychanged or changedomestication ~= nil then
		if inst.components.domesticatable:IsDomesticated() then
			inst.components.domesticatable:SetMinObedience(TUNING.BEEFALO_MIN_DOMESTICATED_OBEDIENCE[inst.tendency])

			inst.components.combat:SetDefaultDamage(TUNING.BEEFALO_DAMAGE[inst.tendency])
			inst.components.locomotor.runspeed = TUNING.BEEFALO_RUN_SPEED[inst.tendency]
		else
			inst.components.domesticatable:SetMinObedience(0)

			inst.components.combat:SetDefaultDamage(TUNING.BEEFALO_DAMAGE.DEFAULT)
			inst.components.locomotor.runspeed = TUNING.BEEFALO_RUN_SPEED.DEFAULT
		end

		inst:ApplyBuildOverrides(inst.AnimState)
		if inst.components.rideable and inst.components.rideable:GetRider() ~= nil then
			inst:ApplyBuildOverrides(inst.components.rideable:GetRider().AnimState)
		end
	end
end

local function ShouldBeg(inst)
	local herd = inst.components.herdmember and inst.components.herdmember:GetHerd()
	return inst.components.domesticatable ~= nil and inst.components.domesticatable:GetDomestication() > 0 and
		inst.components.hunger ~= nil and
		inst.components.hunger:GetPercent() < TUNING.BEEFALO_BEG_HUNGER_PERCENT and
		(herd and herd.components.mood ~= nil and herd.components.mood:IsInMood() == false) and
		(inst.components.mood ~= nil and inst.components.mood:IsInMood() == false)
end

local function CalculateBuckDelay(inst)
	local obedience = inst.components.domesticatable ~= nil and inst.components.domesticatable:GetObedience() or 0

	local moodmult = 1
	--[[(   (inst.components.herdmember ~= nil and inst.components.herdmember.herd ~= nil and inst.components.herdmember.herd.components.mood ~= nil and inst.components.herdmember.herd.components.mood:IsInMood()) or            (inst.components.mood ~= nil and inst.components.mood:IsInMood())   )
    and TUNING.BEEFALO_BUCK_TIME_MOOD_MULT
    or 1]]
	local domesticmult =
		inst.components.domesticatable:IsDomesticated() and 1 or TUNING.BEEFALO_BUCK_TIME_UNDOMESTICATED_MULT

	local basedelay =
		obedience > TUNING.BEEFALO_MIN_BUCK_OBEDIENCE and
		Remap(obedience, TUNING.BEEFALO_MIN_BUCK_OBEDIENCE, 1, TUNING.BEEFALO_MIN_BUCK_TIME, TUNING.BEEFALO_MAX_BUCK_TIME) or
		(Remap(obedience, 0, TUNING.BEEFALO_MIN_BUCK_OBEDIENCE, 0, TUNING.BEEFALO_MIN_BUCK_TIME) +
			math.random() * TUNING.BEEFALO_BUCK_TIME_VARIANCE)

	return basedelay * moodmult * domesticmult
end

local function OnBuckTime(inst)
	--V2C: reschedule because :Buck() is not guaranteed!
	inst._bucktask = inst:DoTaskInTime(1 + math.random(), OnBuckTime)
	inst.components.rideable:Buck()
end

local function OnObedienceDelta(inst, data)
	--inst.components.rideable:SetSaddleable(data.new >= TUNING.BEEFALO_SADDLEABLE_OBEDIENCE)
	inst.components.rideable:SetSaddleable(0)
	if data.new > data.old and inst._bucktask ~= nil then
		--Restart buck timer if we gained obedience!
		inst._bucktask:Cancel()
		inst._bucktask = inst:DoTaskInTime(CalculateBuckDelay(inst), OnBuckTime)
	end
end

local function OnDeath(inst, data)
	inst.persists = false
	inst:AddTag("NOCLICK")
	if inst.components.rideable:IsBeingRidden() then
		--SG won't handle "death" event while we're being ridden
		--SG is forced into death state AFTER dismounting (OnRiderChanged)
		inst.components.rideable:Buck(true)
	end

	local dark2 = SpawnPrefab("statue_transition_2")
	dark2.Transform:SetPosition(inst.Transform:GetWorldPosition():Get())
	if inst.components.container then
		inst.components.container:DropEverything()
	end
end

local function DomesticationTriggerFn(inst)
	return inst.components.hunger:GetPercent() > 0 or inst.components.rideable:IsBeingRidden() == true
end

local function OnEat(inst, food)
	local full = inst.components.hunger:GetPercent() >= 1
	inst:PushEvent("eat", {full = full, food = food})
	inst.components.knownlocations:RememberLocation("loiteranchor", inst:GetPosition())

	local food_value =
		food.components.edible and
		0.3 * food.components.edible.hungervalue + 0.2 * food.components.edible.sanityvalue +
			0.5 * food.components.edible.healthvalue or
		5

	inst.components.health:SetMaxHealth(math.min(inst.components.health.maxhealth + food_value, 1500))
end

local function BreedArong(inst) --被骑的函数
	local musha = inst.components.rideable:GetRider()

	if musha and musha:HasTag("groggy") then --#TODO:
		inst.components.locomotor.runspeed = 5
	else
		inst.components.locomotor.runspeed = 12
	end

	if inst.components.health:GetPercent() < 0.1 or inst.components.hunger:GetPercent() < 0.1 then
		if inst.components.rideable and inst.components.rideable:GetRider() ~= nil then
			inst.components.rideable:Buck(true)
		end
	end

	if inst.components.rideable and inst.components.rideable:GetRider() ~= nil then
		inst.components.hunger:SetRate(TUNING.BEEFALO_HUNGER_RATE * 1.5)
	elseif inst.components.rideable and not inst.components.rideable:GetRider() then
		inst.components.hunger:SetRate(0)
	--inst.components.hunger:DoDelta(0.5)
	end
end

local function on_wakeup(inst, data)
	if inst.components.hunger:GetPercent() < 0.5 then
		SpawnPrefab("pine_needles_chop").Transform:SetPosition(inst:GetPosition():Get())
	end
	local x, y, z = inst.Transform:GetWorldPosition()
	local ents = TheSim:FindEntities(x, y, z, 5, {"musha"})
	for k, v in pairs(ents) do
		if inst.components.follower.leader and (v.sleep_on or v.tiny_sleep) then
			--inst.sg:GoToState("sleeping")
			inst.force_sleep = true
			inst.onsleep = true
			inst.sleep_on = true
		elseif inst.components.follower.leader and not (v.sleep_on or v.tiny_sleep) then
			if inst.components.sleeper:IsAsleep() then
				inst.components.sleeper:WakeUp()
			end
			inst.force_sleep = false
			inst.onsleep = false
			inst.sleep_on = false
		end
	end
end

local function OnDomesticationDelta(inst, data)
	inst:SetTendency()
end

local function OnHealthDelta(inst, data)
	if data.oldpercent >= 0.2 and data.newpercent < 0.2 and inst.components.rideable.rider ~= nil then
		inst.components.rideable.rider:PushEvent("mountwounded")
	end
end

local function DoRiderSleep(inst, sleepiness, sleeptime)
	inst._ridersleeptask = nil
	inst.components.sleeper:AddSleepiness(sleepiness, sleeptime)
end

local function OnRiderChanged(inst, data)
	if inst._bucktask ~= nil then
		inst._bucktask:Cancel()
		inst._bucktask = nil
	end

	if inst._ridersleeptask ~= nil then
		inst._ridersleeptask:Cancel()
		inst._ridersleeptask = nil
	end

	if data.newrider ~= nil then
		if inst.components.sleeper ~= nil then
			inst.components.sleeper:WakeUp()
		end
		inst._bucktask = inst:DoTaskInTime(CalculateBuckDelay(inst), OnBuckTime)
		inst.components.knownlocations:RememberLocation("loiteranchor", inst:GetPosition())
	elseif inst.components.health:IsDead() then
		if inst.sg.currentstate.name ~= "death" then
			inst.sg:GoToState("death")
		end
	elseif inst.components.sleeper ~= nil then
		inst.components.sleeper:StartTesting()
		if inst._ridersleep ~= nil then
			local sleeptime = inst._ridersleep.sleeptime + inst._ridersleep.time - GetTime()
			if sleeptime > 2 then
				inst._ridersleeptask = inst:DoTaskInTime(0, DoRiderSleep, inst._ridersleep.sleepiness, sleeptime)
			end
			inst._ridersleep = nil
		end
	end
end

local function OnSaddleChanged(inst, data)
	--[[if data.saddle ~= nil then
        inst:AddTag("companion")
    else
        inst:RemoveTag("companion")
    end]]
end

local function ShouldWakeUp(inst)
	return
end
local function ArongSleepTest(inst)
	--return not inst.components.rideable:IsBeingRidden() and DefaultSleepTest(inst)
	return not inst.components.rideable:IsBeingRidden() and inst.onsleep and inst.sleep_on
end

local function _OnRefuseRider(inst)
	if inst.components.sleeper:IsAsleep() and not inst.components.health:IsDead() then
		-- this needs to happen after the stategraph
		inst.components.sleeper:WakeUp()
	end
end

local function OnRefuseRider(inst, data)
	inst:DoTaskInTime(0, _OnRefuseRider)
end

local function OnRiderSleep(inst, data)
	inst._ridersleep =
		inst.components.rideable:IsBeingRidden() and
		{
			time = GetTime(),
			sleepiness = data.sleepiness,
			sleeptime = data.sleeptime
		} or
		nil
end

local function MountSleepTest(inst)
	return not inst.components.rideable:IsBeingRidden() and DefaultSleepTest(inst)
end

local function OnInit(inst)
	inst.components.mood:ValidateMood()
	inst:UpdateDomestication()
end

local function CustomOnHaunt(inst)
	inst.components.periodicspawner:TrySpawn()
	return true
end

local function OnSave(inst, data)
	data.tendency = inst.tendency
	data.ownerid = inst.ownerid
end

local function OnLoad(inst, data)
	if data and data.tendency then
		inst.tendency = data.tendency
		inst.ownerid = data.ownerid
	end
end

local function GetDebugString(inst)
	return "tendency: " .. inst.tendency
end

local function common_fn(name)
	local inst = CreateEntity()

	inst.name = name

	inst.entity:AddTransform()
	inst.entity:AddAnimState()
	inst.entity:AddSoundEmitter()
	inst.entity:AddDynamicShadow()
	inst.entity:AddNetwork()

	MakeCharacterPhysics(inst, 100, .5)
	inst.Physics:SetDontRemoveOnSleep(true)
	inst.DynamicShadow:SetSize(6, 2)
	inst.Transform:SetSixFaced()

	inst.AnimState:SetBank("beefalo")
	inst.AnimState:SetBuild(name .. "_build")

	inst.AnimState:PlayAnimation("idle_loop", true)
	inst.AnimState:Hide("HEAT")

	inst.entity:AddMiniMapEntity()
	inst.MiniMapEntity:SetIcon(name .. ".tex")

	inst:AddTag("beefalo")
	inst:AddTag("musha_follower")
	inst:AddTag("musha_beefalo")
	inst:AddTag("animal")
	inst:AddTag("companion")
	inst:AddTag("notraptrigger")
	inst:AddTag("musha_beefalo")
	inst:AddTag("largecreature")
	inst:AddTag("bearded")
	inst:AddTag("saddleable")
	inst:AddTag("saltlicker")
	inst:AddTag("domesticatable")

	--inst:AddTag("herdmember")

	inst.sounds = sounds

	inst:AddComponent("talker")
	inst.components.talker.fontsize = 30
	inst.components.talker.colour = Vector3(0.6, 0.9, 0.8, 1)

	inst.entity:SetPristine()

	if not TheWorld.ismastersim then
		return inst
	end

	inst:AddComponent("container")
	inst.components.container:WidgetSetup("musha_chest_4")
	inst.components.container.onopenfn = OnOpen
	inst.components.container.onclosefn = OnClose

	inst:AddComponent("named")

	inst:AddComponent("playerprox")
	inst.components.playerprox:SetDist(10, 10)

	inst:AddComponent("sanityaura")
	inst.components.sanityaura.aura = TUNING.SANITYAURA_SMALL_TINY

	inst:AddComponent("brushable")
	inst.components.brushable.regrowthdays = 1
	inst.components.brushable.max = 1
	inst.components.brushable.prize = "beefalowool"

	inst:AddComponent("eater")
	inst.components.eater:SetDiet({FOODTYPE.VEGGIE, FOODTYPE.ROUGHAGE}, {FOODTYPE.VEGGIE, FOODTYPE.ROUGHAGE})
	--inst.components.eater:SetAbsorptionModifiers(4,1,1)
	inst.components.eater:SetOnEatFn(OnEat)

	inst:AddComponent("combat")
	inst.components.combat.hiteffectsymbol = "beefalo_body"
	inst.components.combat:SetDefaultDamage(TUNING.BEEFALO_DAMAGE.DEFAULT)
	inst.components.combat:SetRetargetFunction(1, Retarget)
	inst.components.combat:SetKeepTargetFunction(KeepTarget)
	inst.components.combat.playerdamagepercent = 0

	inst:AddComponent("health")
	inst.components.health:SetMaxHealth(600)
	inst.components.health.nofadeout = true
	inst:ListenForEvent("death", OnDeath)
	inst:ListenForEvent("healthdelta", OnHealthDelta)

	inst:AddComponent("lootdropper")
	inst.components.lootdropper:SetChanceLootTable(name)

	inst:AddComponent("inspectable")
	inst.components.inspectable.getstatus = GetStatus

	inst:AddComponent("knownlocations")
	inst:ListenForEvent("entermood", OnEnterMood)
	inst:ListenForEvent("leavemood", OnLeaveMood)

	inst:AddComponent("leader")
	inst:AddComponent("follower")
	inst.components.follower:KeepLeaderOnAttacked()
	inst.components.follower.keepdeadleader = true
	inst.components.follower.canaccepttarget = false

	inst:ListenForEvent("attacked", OnAttacked)

	--[[ inst:AddComponent("periodicspawner")--#TODO:驯化拉屎
	inst.components.periodicspawner:SetPrefab("poop")
	inst.components.periodicspawner:SetRandomTimes(40, 60)
	inst.components.periodicspawner:SetDensityInRange(20, 2)
	inst.components.periodicspawner:SetMinimumSpacing(8)
	inst.components.periodicspawner:Start() ]]
	inst:AddComponent("rideable")
	inst.components.rideable:SetRequiredObedience(0)

	inst:ListenForEvent("saddlechanged", OnSaddleChanged)
	inst:ListenForEvent("refusedrider", OnRefuseRider)

	inst:AddComponent("trader")
	inst.components.trader:SetAcceptTest(ShouldAcceptItem)
	inst.components.trader.onaccept = OnGetItemFromPlayer
	inst.components.trader.onrefuse = OnRefuseItem
	inst.components.trader.deleteitemonaccept = false

	inst:AddComponent("maprevealer")
	inst.components.maprevealer.revealperiod = 0.25
	inst.components.maprevealer:Start()

	inst:AddComponent("hunger")
	inst.components.hunger:SetMax(400)

	inst.components.hunger:SetRate(0)

	inst:AddComponent("domesticatable")
	inst.components.domesticatable:SetDomesticationTrigger(DomesticationTriggerFn)

	MakeLargeBurnableCharacter(inst, "beefalo_body")
	MakeLargeFreezableCharacter(inst, "beefalo_body")

	inst:AddComponent("locomotor")
	inst.components.locomotor.walkspeed = 0.5
	inst.components.locomotor.runspeed = TUNING.BEEFALO_RUN_SPEED.DEFAULT
	inst:AddComponent("sleeper")
	inst.components.sleeper:SetResistance(5)
	inst.components.sleeper.sleeptestfn = MountSleepTest

	inst:AddComponent("timer")

	inst:AddComponent("saltlicker")
	inst.components.saltlicker:SetUp(TUNING.SALTLICK_BEEFALO_USES)

	inst.ApplyBuildOverrides = ApplyBuildOverrides
	inst.ClearBuildOverrides = ClearBuildOverrides

	inst.tendency = TENDENCY.DEFAULT
	inst._bucktask = nil

	inst.components.health:SetAbsorptionAmount(0.6)
	inst.components.health:StartRegen(1, 15)

	inst:AddComponent("herdmember")
	inst.components.herdmember:Enable(false)

	--#TODO:删掉？
	inst:AddComponent("mood")
	inst.components.mood:SetMoodTimeInDays(TUNING.BEEFALO_MATING_SEASON_LENGTH, TUNING.BEEFALO_MATING_SEASON_WAIT)
	inst.components.mood:SetInMoodFn(OnEnterMood)
	inst.components.mood:SetLeaveMoodFn(OnLeaveMood)
	inst.components.mood:CheckForMoodChange()
	inst.components.mood:Enable(false)

	inst.UpdateDomestication = UpdateDomestication
	inst:ListenForEvent("domesticated", OnDomesticated)
	inst.DoFeral = DoFeral
	inst:ListenForEvent("goneferal", OnFeral)
	inst:ListenForEvent("obediencedelta", OnObedienceDelta)
	inst:ListenForEvent("domesticationdelta", OnDomesticationDelta)
	inst:ListenForEvent("riderchanged", OnRiderChanged)
	inst:ListenForEvent("ridersleep", OnRiderSleep)

	inst:AddComponent("uniqueid")
	inst:AddComponent("beefalometrics")

	inst:ListenForEvent("attacked", flower_shield)
	--inst.on_follow = inst:DoPeriodicTask(1, on_follow)
	--inst.on_wakeup = inst:DoPeriodicTask(4, on_wakeup)
	inst.BreedArong = inst:DoPeriodicTask(1, BreedArong)

	MakeHauntablePanic(inst)
	AddHauntableCustomReaction(inst, CustomOnHaunt, true, false, true)

	inst.SetTendency = SetTendency
	inst:SetTendency()

	inst.ShouldBeg = ShouldBeg

	inst:SetBrain(brain)

	inst:SetStateGraph("SGBeefalo")
	inst:DoTaskInTime(0, OnInit)
	if not inst.components.follower.leader then
		inst.components.hunger:SetRate(0)
	end

	inst.debugstringfn = GetDebugString
	inst.OnSave = OnSave
	inst.OnLoad = OnLoad
	inst.order = order

	return inst
end

local function arong()
	return common_fn("arong")
end
local function arom()
	return common_fn("arom")
end

return Prefab("musha_arong", arong, assets_arong, prefabs), Prefab("musha_arom", arom, assets_arom, prefabs)
